﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Ionic.Zip;
using System.IO;
using System.Xml;

namespace Study_Time
{
    public partial class StudyControl : UserControl
    {
        public Boolean FileLoaded { get; set; }
        public String FileName { get; set; }

        public Boolean NeedsToSave { get; set; }

        public const int buttonOffset = 5;

        public StudyControl()
        {
            InitializeComponent();

            // No file is loaded
            FileLoaded = false;
            FileName = "";
            NeedsToSave = false;
        }

        // Must listen for this event if we want to use DranDrop
        private void StudyControl_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void StudyControl_DragDrop(object sender, DragEventArgs e)
        {
            // Grab list of files from the drag and drop
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

            // Select the first file and compare the extension.
            // Right now there is only support for jpg files and stf files.
            if (files[0].EndsWith(".jpg") || files[0].EndsWith(".JPG"))
            {
                // Load the image file
                LoadImage(files[0]);
            }
            else if (files[0].EndsWith(".stf") || files[0].EndsWith(".STF"))
            {
                // Load the stf file
                LoadStf(files[0]);
            }
            else
                MessageBox.Show("You may only open the following file types: jpg, stf.", "Oops", MessageBoxButtons.OK);
        }

        private void pictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (Program.Mode == Program.StudyTimeMode.Study)
            {
                // DO NOT ADD A NEW SPOT BUTTON
            }
            else if (Program.Mode == Program.StudyTimeMode.Edit)
            {
                // Create a new StudyButton
                StudyButton studyButton = new StudyButton(e.X - buttonOffset, e.Y - buttonOffset, "");

                // Add a new StudyButton to the PictureBox
                pictureBox.Controls.Add(studyButton);

                // Since we are in edit mode, go ahead and open this button
                studyButton.Open();
            }
        }

        public void Reset()
        {
            // Close all of the buttons
            CloseAllButtons();

            // Make each button gray again
            foreach (StudyButton studyButton in pictureBox.Controls)
            {
                studyButton.Reset();
            }
        }

        private void CloseAllButtons()
        {
            foreach (StudyButton studyButton in pictureBox.Controls)
            {
                studyButton.Close();
            }
        }

        public void Save()
        {
            // If there is not file name
            if (FileName.Equals(""))
                SaveAs();
            else
            {
                // Save the file
                Save(FileName);
            }
        }

        public void SaveAs()
        {
            // Show the SaveFileDialog and save as a .stf file
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.AddExtension = true;
            saveFileDialog.FileName = FileName;
            saveFileDialog.Filter = "Study Time File (*.stf)|*.stf";
            saveFileDialog.ShowDialog();

            // If a file name was given, then save the file
            if (!saveFileDialog.FileName.Equals(""))
            {
                // Save the current file name
                FileName = GetFileNameFromPath(saveFileDialog.FileName);

                Save(saveFileDialog.FileName);
            }
        }

        private void Save(String filePath)
        {
            String tempDirectory = Path.GetTempPath() + "Study Time Save Temp";
            String imageFile = tempDirectory + "\\Image.jpg";
            String xmlFile = tempDirectory + "\\StudyTimeFileData.xml";

            // Close all of the button before saving.
            // This needs to be done because closing them is the
            // event that makes the button store the text
            // it its UserProvidedText variable
            if (Program.Mode == Program.StudyTimeMode.Edit)
                CloseAllButtons();

            // Create the temporary folder before saving the temp files
            Directory.CreateDirectory(tempDirectory);

            // Save the temp files before adding them to the zip folder
            pictureBox.Image.Save(imageFile);
            File.WriteAllText(xmlFile, CreateStudyTimeFileDataXMLString());

            // Create a ZipFile object
            using (ZipFile zipFile = new ZipFile())
            {
                // Add files to the zip folder in the root of the zip folder
                zipFile.AddFile(imageFile, "");
                zipFile.AddFile(xmlFile, "");

                // Save the zip folder
                zipFile.Save(filePath);
            }

            // Delete the temporary directory
            Directory.Delete(tempDirectory, true);

            // Since we have saved, change the NeedsToSave variable
            NeedsToSave = false;
        }

        public void LoadImage(String imageFile)
        {
            String tempDirectory = Path.GetTempPath() + "Study Time Load Temp";
            String tempImageFile = tempDirectory + "\\Image.jpg";

            // Since we are loading an image, this will be a new file.  Make
            // the program enter edit mode.
            Program.Mode = Program.StudyTimeMode.Edit;

            // Clear the currently loaded stf or image file
            Clear();

            // Create the temporary folder before saving the file there
            Directory.CreateDirectory(tempDirectory);

            // Save the image file in the temp directory
            File.Copy(imageFile, tempImageFile, true);

            // Set the picture box image
            pictureBox.Image = Image.FromFile(tempImageFile);

            // The file is loaded
            FileLoaded = true;
        }

        public void LoadStf(String stfFile)
        {
            String tempDirectory = Path.GetTempPath() + "Study Time Load Temp";
            String tempImageFile = tempDirectory + "\\Image.jpg";
            String tempXMLFile = tempDirectory + "\\StudyTimeFileData.xml";

            // Since we are loading an stf file, we can assume that we should enter study mode
            Program.Mode = Program.StudyTimeMode.Study;

            // Clear the currently loaded stf or image file
            Clear();

            // Create the temporary folder before saving the temp files
            Directory.CreateDirectory(tempDirectory);

            // Save the temp files before loading them into the program
            using (ZipFile zipFile = ZipFile.Read(stfFile))
            {
                foreach (ZipEntry zipEntry in zipFile)
                {
                    zipEntry.Extract(tempDirectory, ExtractExistingFileAction.OverwriteSilently);
                }
            }

            // Load the image
            pictureBox.Image = Image.FromFile(tempImageFile);

            // Load the XML data
            LoadXMLData(tempXMLFile);

            // The file is loaded
            FileLoaded = true;

            // Store the file name, but not the path
            FileName = GetFileNameFromPath(stfFile);
        }

        private String GetFileNameFromPath(String filePath)
        {
            String[] sections = filePath.Split('\\');

            return sections[sections.Length - 1];
        }

        private void LoadXMLData(String xmlFile)
        {
            using (XmlReader xmlReader = XmlReader.Create(xmlFile))
            {
                // Read the buttons tag
                xmlReader.ReadToFollowing("buttons");

                // While there are still button tags
                while (xmlReader.ReadToFollowing("button"))
                {
                    int xPosition;
                    int yPosition;
                    String userProvidedText;

                    // Read the x-position content
                    xmlReader.ReadToFollowing("x-position");
                    xmlReader.MoveToContent();
                    xmlReader.Read();
                    
                    // Store the x position
                    xPosition = Int32.Parse(xmlReader.Value);

                    // Read the y-position content
                    xmlReader.ReadToFollowing("y-position");
                    xmlReader.MoveToContent();
                    xmlReader.Read();

                    // Store the y position
                    yPosition = Int32.Parse(xmlReader.Value);

                    // Read the user-provided-text content
                    xmlReader.ReadToFollowing("user-provided-answer");
                    xmlReader.MoveToContent();
                    xmlReader.Read();

                    // Store the user provided text
                    userProvidedText = xmlReader.Value;

                    // Create a new SpotButton with the stored information and add it to the pictureBox
                    pictureBox.Controls.Add(new StudyButton(xPosition, yPosition, userProvidedText));
                }
            }
        }

        private void Clear()
        {
            // Clear the buttons
            pictureBox.Controls.Clear();

            // Clear the picture box
            if (pictureBox.Image != null)
                pictureBox.Image.Dispose();
        }

        private String CreateStudyTimeFileDataXMLString()
        {
            String xmlString =
                "<study-time-file-data>\n" +
                "   <buttons>\n";

            foreach (StudyButton spotButton in pictureBox.Controls)
            {
                xmlString +=
                    "      <button>\n" +
                    "         <x-position>" + spotButton.Location.X + "</x-position>\n" +
                    "         <y-position>" + spotButton.Location.Y + "</y-position>\n" +
                    "         <user-provided-answer>" + spotButton.UserProvidedAnswer + "</user-provided-answer>\n" +
                    "      </button>\n";
            }

            xmlString +=
                "   </buttons>\n" +
                "</study-time-file-data>\n";

            return xmlString;
        }
    }
}
